package com.litchi.tutor.common.aop;

import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;


/**
 * @author hoby
 * @since 2021-08-19
 */
@Slf4j
@Aspect
@Component
public class LogAspect {

    @Around("execution(* com.*.rest.*.*(..)))")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        StringBuilder name = null;
        TimeInterval interval = new TimeInterval();
        try {
            // 接口名称
            String className = pjp.getTarget().getClass().getSimpleName();
            String methodName = pjp.getSignature().getName();
            // 下载接口不打印日志
            if (StrUtil.containsAny(methodName, "download", "import", "export")) {
                return pjp.proceed();
            }
            name = new StringBuilder(className).append(":").append(methodName);

            // 接口入参
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            Object arg = ArrayUtil.get(pjp.getArgs(), 0);
            String queryString = request.getQueryString();
            if (arg == null) {
                log.info("接口:{} 入参:{}", name, queryString);
            } else {
                log.info("接口:{} 入参:{}", name, JSON.toJSONString(arg));
            }

            // 接口出参
            Object o = pjp.proceed();
            log.info("接口:{} 出参:{}", name, JSON.toJSONString(o));
            return o;
        } catch (Throwable throwable) {
            log.error("接口:" + name + " 抛异常");
            throw throwable;
        } finally {
            log.info("接口:{} 耗时:{}ms", name, interval.intervalMs());
        }
    }
}
